package com.kk.xhr.web.vo;

import com.kk.xhr.common.ErrorCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.context.MessageSource;

import java.io.Serializable;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

/**
 * 通用返回值包装类
 *
 * @author luokexiong
 * @version 1.0 2021/2/13
 * @since 1.0.0
 */
@ApiModel
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class ApiResult<T> implements Serializable {
    @ApiModelProperty(value = "是否成功", dataType = "Boolean")
    private boolean success;
    @ApiModelProperty(value = "错误码", example = "0")
    private int code;
    @ApiModelProperty(value = "返回数据", dataType = "Object")
    private T data;
    @ApiModelProperty(value = "错误信息", example = "ok")
    private String message;

    public static <T> ApiResult<T> success() {
        return new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), null, ErrorCodeEnum.OK.name());
    }

    public static <T> ApiResult<T> success(MessageSource messageSource, Locale locale) {
        return new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), null,
                messageSource.getMessage(ErrorCodeEnum.OK.getMessage(), null, locale));
    }

    public static <T> ApiResult<T> success(T data) {
        return new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), data, ErrorCodeEnum.OK.name());
    }

    public static <T> CompletionStage<ApiResult<T>> successASync(T data) {
        return CompletableFuture.completedFuture(
                new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), data, ErrorCodeEnum.OK.name()));
    }

    public static <T> ApiResult<T> failed(int errorCode, String errorMsg) {
        return new ApiResult<>(false, errorCode, null, errorMsg);
    }

    public static <T> ApiResult<T> failed(ErrorCodeEnum errorCode, T data, String errorMsg) {
        return new ApiResult<>(false, errorCode.getCode(), data, errorMsg);
    }

    public static <T> ApiResult<T> failed(ErrorCodeEnum error) {
        return new ApiResult<>(false, error.getCode(), null, error.getMessage());
    }

    public static <T> ApiResult<T> failed(ErrorCodeEnum error, MessageSource messageSource, Locale locale) {
        return new ApiResult<>(false, error.getCode(), null, messageSource.getMessage(error.getMessage(), null, locale));
    }

    public static <T> CompletionStage<ApiResult<T>> failedAsync(ErrorCodeEnum error, MessageSource messageSource, Locale locale) {
        return CompletableFuture.completedFuture(new ApiResult<>(false, error.getCode(), null,
                messageSource.getMessage(error.getMessage(), null, locale)));
    }

    public static <T> ApiResult<T> failed(ErrorCodeEnum error, MessageSource messageSource, Locale locale, Object[] args) {
        return new ApiResult<>(false, error.getCode(), null, messageSource.getMessage(error.getMessage(), args, locale));
    }

    public static <T> ApiResult<T> parameterFailed(ErrorCodeEnum error, T data, MessageSource messageSource, Locale locale) {
        return new ApiResult<>(false, error.getCode(), data, messageSource.getMessage(error.getMessage(), null, locale));
    }

    public static <T> CompletionStage<ApiResult<T>> parameterFailedAsync(ErrorCodeEnum error, T data, MessageSource messageSource, Locale locale) {
        return CompletableFuture.completedFuture(new ApiResult<>(false, error.getCode(), data,
                messageSource.getMessage(error.getMessage(), null, locale)));
    }

    public static <T> ApiResult<T> successForMsg(String msgKey, MessageSource messageSource, Locale locale, Object[] args) {
        return new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), null, messageSource.getMessage(msgKey, args, locale));
    }

    public static <T> ApiResult<T> successForMsg(String msgKey, T data, MessageSource messageSource, Locale locale, Object[] args) {
        return new ApiResult<>(true, ErrorCodeEnum.OK.getCode(), data, messageSource.getMessage(msgKey, args, locale));
    }

    public static <T> ApiResult<T> failedForMsg(ErrorCodeEnum errorCode, T data, MessageSource messageSource, Locale locale, Object[] args) {
        return new ApiResult<>(false, errorCode.getCode(), data, messageSource.getMessage(errorCode.getMessage(), args, locale));
    }

    public static <T> ApiResult<T> failedForMsg(String msgKey, MessageSource messageSource, Locale locale, Object[] args) {
        return new ApiResult<>(true, ErrorCodeEnum.UNKNOWN_ERROR.getCode(), null, messageSource.getMessage(msgKey, args, locale));
    }
}
